package com.example.springstudy.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import com.example.springstudy.entity.SysUserDetails;
import com.example.springstudy.entity.User;
import com.example.springstudy.mapper.UserMapper;
import com.example.springstudy.dao.res.LoginRes;
import com.example.springstudy.service.AuthService;
import com.example.springstudy.utils.JwtUtil;
import com.example.springstudy.utils.RedisUtils;
import com.example.springstudy.utils.SecurityUtils;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    AuthenticationManager manager;

    String BLACKLIST_TOKEN_PREFIX = "BLACKLIST_TOKEN_PREFIX";

    @Override
    public LoginRes login(String username, String password) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authentication = manager.authenticate(authenticationToken);
        String token = JwtUtil.createToken(authentication);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        Object principal = authentication.getPrincipal();
        SysUserDetails sysUserDetails = (SysUserDetails) principal;
        LoginRes res = new LoginRes();
        res.setUser(sysUserDetails.getUser());
        res.setToken(token);
        return res;
    }

    @Override
    public void register(User user) {

    }

    @Override
    public void logout() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StrUtil.isNotBlank(token) && token.startsWith(SecurityUtils.prefix)) {
            token = token.substring(SecurityUtils.prefix.length());
            // 解析Token以获取有效载荷（payload）
            JSONObject payloads = JWTUtil.parseToken(token).getPayloads();
            // 解析 Token 获取 jti(JWT ID) 和 exp(过期时间)
            String jti = payloads.getStr(JWTPayload.JWT_ID);
            Long expiration = payloads.getLong(JWTPayload.EXPIRES_AT); // 过期时间(秒)
            // 如果exp存在，则计算Token剩余有效时间
            if (expiration != null) {
                long currentTimeSeconds = System.currentTimeMillis() / 1000;
                if (expiration < currentTimeSeconds) {
                    // Token已过期，不再加入黑名单
                    return;
                }
                // 将Token的jti加入黑名单，并设置剩余有效时间，使其在过期后自动从黑名单移除
                long ttl = expiration - currentTimeSeconds;
                redisUtils.expire(BLACKLIST_TOKEN_PREFIX + jti, ttl);
            } else {
                // 如果exp不存在，说明Token永不过期，则永久加入黑名单
                redisUtils.set(BLACKLIST_TOKEN_PREFIX + jti, null);
            }
        }
        // 清空Spring Security上下文
        SecurityContextHolder.clearContext();
    }
}
